{**  
 * @brief Alone_Lumberjacking - 脱机伐木脚本  
 * @author Alone  
 * @date 2022.08.17  
 *  
 * 运行要求：  
 * 1. 魔法或圣骑技能100%飞成功  
 * 2. 斧子带通道属性（如果使用魔法飞行）  
 * 3. 5本刻满伐木点的飞书  
 * 4. 2颗不同点的符石，用于木头箱存取  
 * 5. 事先生成伐木点坐标文件  
 *}  

{**
  ### 功能讲解  
    
  1. **初始化**：设置常量、变量，加载GM列表和伐木点坐标文件。  
    
  2. **主循环**：脚本运行的主逻辑，包括连接到游戏、飞往木头箱、伐木循环等。  
    
  3. **飞往木头箱**：使用飞行书快速移动到预设的木头箱位置。  
    
  4. **伐木循环**：遍历所有的飞书和伐木点，对每个点进行伐木操作。包括飞行到点、检测并砍伐树木、处理伐木成果等步骤。  
    
  5. **处理伐木成果**：将伐得的木头和其他副产品存放到木头箱中。  
    
  6. **额外逻辑**：处理断线重连、角色死亡、系统存盘等异常情况，以及GM巡查、验证码提醒等额外功能。  
    
  7. **报告统计**：统计伐木时长、伐得木头数量等信息，并记录在日志中。
 *}  

program Alone_Lumberjacking;  
  
// 以下所有参数必须根据自身实际情况进行修改  
const  
  // 声音报警设置  
  BaoJingSheng = True;        // 是否启用声音报警，报警则设为True，不报警设为False  
  ShengYinWenJian = 'D:\Program Files (x86)\Stealth\alarma.wav'; // 报警声音文件的完整路径  
  
  // 其他设置  
  ZhaoWeiBing = True;         // 是否在砍树时喊"Guard"，需要时设为True，不需要时设为False  
  
  // 飞行技能设置  
  FeiXingJiNeng = 5;          // 飞行的技能代码，魔法为5，圣骑为7  
  
  // 木头箱设置  
  MuTouXiang = $44D91505;     // 木头箱的ID  
  MuTouXiang_X = 2130;        // 木头箱的X坐标  
  MuTouXiang_Y = 875;         // 木头箱的Y坐标  
  
  // 伐木点飞书设置  
  DiYiBenFaMuShu = $436F83C1; // 第一本伐木点飞书的ID  
  DiErBenFaMuShu = $436F7A1E; // 第二本伐木点飞书的ID  
  DiSanBenFaMuShu = $436F6972; // 第三本伐木点飞书的ID  
  DiSiBenFaMuShu = $45791E1E; // 第四本伐木点飞书的ID  
  DiWuBenFaMuShu = $4578FF88; // 第五本伐木点飞书的ID  
  
  // 回家的飞书设置  
  FeiHuiShu = $41B6A739;      // 回家的飞书的ID  
  DiYiHuiJiaDian = 1;         // 飞回家的第一颗符石在回家的飞书中的位置（1~16）  
  
  // 伐木朝向设置  
  FaMuFangXiang = 1;          // 伐木时的朝向，0为北(N)，1为东(E)，2为南(S)，3为西(W)  
  
  // 系统存盘时间设置  
  CunPanShiJian = 200;        // 系统存盘时间，单位为0.1秒，应略长于实际存盘时间
  
// 数据类型定义  
Type  
  // 坐标点记录  
  ZuoBiaoDian = record  
    X_ZuoBiao: Word;  
    Y_ZuoBiao: Word;  
  end;  
   
// 声明全局变量  
var  
  // 游戏管理员名称列表，用于检测GM  
  GMName: array of String;  
    
  // 可能是物品或图形ID的数组  
  ShuTuXing: array of Word;  
    
  // 坐标点数组，存储伐木点的位置  
  ZuoBiaoJi: array of ZuoBiaoDian;  
    
  // 与产物、搜索结果和伐木数量相关的数组  
  FuChanPinTuXing: array of Cardinal; // 副产品类型数组  
  SouSuoJieGuo: array of Cardinal;    // 搜索结果数组  
  FaMuShu: array of Cardinal;         // 伐木书数组  
    
  // 静态地图单元，可能代表某个特定区域或对象  
  QuTuXing: TStaticCell;  

  // 当前位置和状态相关的变量  
  DangQianShu, ShuX, ShuY: Word;              // 当前树木位置变量  
  nowX, nowY: Word;                           // 当前位置坐标  
  LinShi_X_ZuoBiao, LinShi_Y_ZuoBiao: Word;   // 临时坐标变量
  JiShiZuoBiaoX, JiShiZuoBiaoY: Word;         // 记录坐标变量
    
  // 负重和预备值相关的变量  
  ZuiDaFuZhong, DangQianFuZhong: Word;        // 最大负重和当前负重  
  PiYuZhi, HuiYuZhi: Word;                    // 用途不明
    
  // 其他数值变量  
  ShuZ: ShortInt;                             // 短整型变量（用途不明）  
  TongJiShiChang: Single;                     // 统计时长或某个数值  
  XianShi, XPianYi, YPianYi: Integer;         // 显示值、X偏移量和Y偏移量  
    
  // 计时器和延迟相关的变量  
  waiMS, waiMS2: Byte;                      // 等待毫秒计数器  
  WeiBingShiJian: Byte;                     // 喊Guard的时间  
  TaoPao, PaoBuShu, FuShi: Byte;            // 
    
  // 循环计数器和其他状态变量  
  h, i, j, k, l, m, n: Byte;                 // 循环计数器或临时变量  
    
  // 时间统计和报警相关的变量  
  BaoJingShiChang: Cardinal;                  // 报警时间
  MuBanShu, MuBanZongJiShu: Cardinal;   // 木板数量
  QiDongShiJian: Cardinal;                    // 脚本启动时间戳  
  ZongShiChang, ShengYuShiChang: Cardinal;    // 总时长和剩余时长  
  TianShu, XiaoShiSHu, FenZhongShu, MiaoZhongShu: Cardinal; // 天数、小时数、分钟数、秒数（用于时间统计）  
    
  YunXingShiChang: String;  //运行时长
    
  // 布尔标志变量，用于控制脚本的行为或状态  
  TaoGuo: Boolean;                            // 是否已经逃跑（或其他相关行为）  
  BaoGao: Boolean;                            // 是否需要报告状态或信息  
  JianCeZuoBiao: Boolean;                     // 是否需要检测坐标变化  
  ZuoBiaoYiChang: Boolean;                    // 坐标是否已经变化（或其他相关状态）  
  
// 下边一行引号中填写本伐木工对应的伐木点文件名，与脚本不在同一目录时须附带路径  
{$Include 'FaMuDian_Fmu.txt'} // 包含伐木点数据文件
   
// 初始化GM列表  
// GM列表，用于问话检测，可根据实际进行增减，注意总数要随之变动  
procedure _GMLieBiao;  
begin  
  setLength(GMName, 9); // 设置GMName数组的长度为9  
  GMName[0] := 'Dysis';  
  GMName[1] := 'Astraeus';  
  GMName[2] := 'Marshall';  
  GMName[3] := 'Samael';  
  GMName[4] := 'Asteria';  
  GMName[5] := 'GM Tetra';  
  GMName[6] := 'Seer Selene';  
  GMName[7] := 'Eos';  
  GMName[8] := 'Larson';  
end;

// 过程：喊Guard  
procedure _HanWeiBing;  
begin  
  // 增加喊话计数器  
  WeiBingShiJian := WeiBingShiJian + 1;  
    
  // 如果喊话计数器等于2  
  if (WeiBingShiJian = 2) then  
  begin  
    // 重置喊话计数器  
    WeiBingShiJian := 0;  
    // 喊出"Guard"  
    UOsay('Guard');  
  end;  
end;
  
// 过程：淘跑
procedure _TaoZhaDan; 
begin  
  // 随机选择一个初始的逃跑方向（假设 TaoPao 是方向变量，范围可能是 0 到 7）  
  TaoPao := Random(8);  
    
  // 循环执行逃跑动作 5 次（从 0 到 4）  
  for PaoBuShu := 0 to 4 do  
  begin  
    // 尝试在当前方向上移动，如果移动的结果不是 7（可能表示遇到障碍物或其他特殊情况）  
    if Step(TaoPao, True) <> 7 then  
    begin  
      // 更新逃跑方向（简单地将方向值加 1）  
      TaoPao := TaoPao + 1;  
        
      // 如果方向值达到 8（超出了可能的范围），则将其重置为 0  
      if (TaoPao = 8) then  
        TaoPao := 0;  
        
      // 在更新后的方向上再次尝试移动  
      Step(TaoPao, True);  
    end;  
  end;  
end;

procedure _FangZhaDan; // 定义放炸弹并治疗的过程  
begin  
  // 如果当前生命值小于最大生命值  
  if (HP < MaxHP) then  
  begin  
    // 如果已经逃跑（假设 TaoGuo 是一个标志变量）  
    if TaoGuo then  
    begin  
      // 重置逃跑标志  
      TaoGuo := False;  
      // 调用逃跑炸弹过程  
      _TaoZhaDan;  
        
      // 根据飞行技能代码判断使用哪种治疗技能  
      if FeiXingJiNeng = 5 then  
      begin  
        // 取消等待目标  
        CancelWaitTarget;  
        // 取消当前目标  
        CancelTarget;  
        // 施放大治疗术  
        Cast('Greater Heal');  
        // 等待目标出现，等待技能效果生效的时间  
        WaitForTarget(4000);  
        // 将目标设置为自己  
        TargetToObject(self);  
        // 等待一段时间，可能是等待生命值恢复  
        Wait(2400);  
      end  
      else if FeiXingJiNeng = 7 then  
      begin  
        // 取消等待目标  
        CancelWaitTarget;  
        // 取消当前目标  
        CancelTarget;  
        // 施放接近伤口治疗术  
        Cast('Close Wounds');  
        // 等待目标出现，等待技能效果生效的时间  
        WaitForTarget(4000);  
        // 将目标设置为自己  
        TargetToObject(self);  
        // 等待一段时间，可能是等待生命值恢复  
        Wait(2400);  
      end;  
    end;  
  end;  
end;
  
// 过程：对话框检测  
procedure _DuiHuaKuangJianCe(Serial, GumpID: Cardinal; X, Y: Integer);  
begin  
  // 如果传入的 GumpID 等于 3279111667  
  if (GumpID = 3279111667) then  
  begin  
    // 遍历所有已打开的 Gump  
    for l := 0 to (GetGumpsCount - 1) do  
    begin  
      // 如果当前 Gump 的 ID 也等于 3279111667  
      if (GetGumpID(l) = 3279111667) then  
      begin  
        // 在系统日志中添加消息“刷验证码了！！！”  
        AddToSystemJournal('刷验证码了！！！');  
        // 跳出循环  
        Break;  
      end;  
    end;  
    // 在系统日志中添加消息“快看验证码”  
    AddToSystemJournal('快看验证码');  
  
    // 如果启用了声音报警（BaoJingSheng 为 True）  
    if BaoJingSheng then  
    begin  
      // 如果当前时间减去上次报警时间大于等于 8000 毫秒（即 8 秒）  
      if (timer - BaoJingShiChang) >= 8000 then  
      begin  
        // 更新上次报警时间为当前时间  
        BaoJingShiChang := timer;  
        // 播放报警声音文件  
        PlayWav(ShengYinWenJian);  
      end;  
    end;  
  end;  
end;
  
// 过程：存盘检测  
procedure _CunPanJianCe;  
begin  
  // 如果系统日志中存在“System: The world is saving”这条消息  
  if (InJournal('System: The world is saving') > -1) then  
  begin  
    // 在系统日志中添加消息“脚本暂停，等候系统存盘完成”  
    AddToSystemJournal('脚本暂停，等候系统存盘完成');  
    // 初始化显示时间计数器  
    XianShi := 0;  
    // 循环检查系统日志，直到出现“System: World save complete”这条消息  
    while InJournal('System: World save complete') = -1 do  
    begin  
      // 等待100毫秒  
      Wait(100);  
      // 显示时间计数器加1  
      XianShi := XianShi + 1;  
      // 如果显示时间超过预设的系统存盘时间，则跳出循环  
      if XianShi >= CunPanShiJian then  
        Break;  
    end;  
    // 清除系统日志中的相关消息  
    ClearJournal;  
  end  
  else if (InJournal('System: The world will save') > -1) then  
  begin  
    // 在系统日志中添加消息“系统即将存盘，等候存盘完成”  
    AddToSystemJournal('系统即将存盘，等候存盘完成');  
    // 初始化显示时间计数器为负值（可能是为了与上面的逻辑有所区分）  
    XianShi := -100;  
    // 循环检查系统日志，直到出现“System: World save complete”这条消息  
    while InJournal('System: World save complete') = -1 do  
    begin  
      // 等待100毫秒  
      Wait(100);  
      // 显示时间计数器加1（尽管初始化为负值，但逻辑上仍然表示时间流逝）  
      XianShi := XianShi + 1;  
      // 如果显示时间超过预设的系统存盘时间，则跳出循环  
      if XianShi >= CunPanShiJian then  
        Break;  
    end;  
    // 清除系统日志中的相关消息  
    ClearJournal;  
  end;  
end;
  
// 过程：断线重连检测  
procedure _DuanXianJianCe;  
begin  
  if not Connected  then
  begin  
    Connect; // 如果未连接，则尝试连接  
    waiMS := 0; // 重置等待计数器  
    repeat  
      Wait(500); // 等待500毫秒  
      waiMS := waiMS + 1; // 增加等待计数器  
      AddToSystemJournal('掉线了，重连中...'); // 在系统日志中添加掉线重连中的消息  
      if waiMS >= 10 then // 如果等待了10次（即5秒）  
      begin  
        Connect; // 再次尝试连接  
        waiMS := 0; // 重置等待计数器  
      end;  
    until Connected; // 循环直到成功连接  
  end;  
end;  
  
// 函数：获取当前X坐标  
function _Du_X_ZuoBiao: Word; // 获取当前X坐标的函数  
begin  
  LinShi_X_ZuoBiao := 0; // 初始化临时变量为0  
  repeat  
    _DuanXianJianCe; // 调用断线重连检测过程  
    LinShi_X_ZuoBiao := GetX(self); // 获取当前对象的X坐标  
  until LinShi_X_ZuoBiao <> 0; // 循环直到获取到非0的X坐标  
  Result := LinShi_X_ZuoBiao; // 返回获取到的X坐标  
end;  
  
// 函数：获取当前Y坐标  
function _Du_Y_ZuoBiao: Word;  
function _Du_Y_ZuoBiao: Word; // 获取当前Y坐标的函数  
begin  
  LinShi_Y_ZuoBiao := 0; // 初始化临时变量为0  
  repeat  
    _DuanXianJianCe; // 调用断线重连检测过程  
    LinShi_Y_ZuoBiao := GetY(self); // 获取当前对象的Y坐标  
  until LinShi_Y_ZuoBiao <> 0; // 循环直到获取到非0的Y坐标  
  Result := LinShi_Y_ZuoBiao; // 返回获取到的Y坐标  
end;
  
// 过程：意外情况处理  
procedure _yiwai;  
begin  
  _DuanXianJianCe; // 断线重连检测  
  
  // 如果角色处于死亡状态  
  while Dead do  
  begin  
    AddToSystemJournal('伐木工已死亡，请赶紧查看！！！'); // 添加日志提示角色死亡  
    Wait(2000); // 等待2秒  
  end;  
  
  // 如果需要检查坐标  
  if JianCeZuoBiao then  
  begin  
    // 获取当前坐标  
    JiShiZuoBiaoX := _Du_X_ZuoBiao;  
    JiShiZuoBiaoY := _Du_Y_ZuoBiao;  
    ZuoBiaoYiChang := True; // 初始化坐标异常标志为True  
  
    // 检查是否在木头箱附近  
    if (Dist(JiShiZuoBiaoX, JiShiZuoBiaoY, MuTouXiang_X, MuTouXiang_Y) < 3) then  
      ZuoBiaoYiChang := False // 如果在木头箱附近，则坐标正常  
    else  
    begin  
      h := ((j - 1) * 16 + k) + 1; // 根据j和k计算h的初始值  
  
      // 检查其他坐标点  
      for m := 1 to 80 do  
      begin  
        h := h - 1; // 递减h的值  
        if (h = 0) then h := 80; // 如果h为0，则循环回80  
  
        // 检查当前坐标点是否接近角色的坐标  
        if (Dist(JiShiZuoBiaoX, JiShiZuoBiaoY, ZuoBiaoJi[h].X_ZuoBiao, ZuoBiaoJi[h].Y_ZuoBiao) < 10) then  
        begin  
          ZuoBiaoYiChang := False; // 如果接近，则坐标正常  
          Break; // 跳出循环  
        end;  
      end;  
    end;  
  
    // 如果坐标异常  
    if ZuoBiaoYiChang then  
    begin  
      AddToSystemJournal('坐标异常，可能被抓了，快看一下！！！'); // 添加日志提示坐标异常  
      if BaoJingSheng then // 如果启用了声音报警  
      begin  
        if (timer - BaoJingShiChang) >= 8000 then // 如果距离上次报警超过8秒  
        begin  
          BaoJingShiChang := timer; // 更新上次报警时间  
          PlayWav(ShengYinWenJian); // 播放报警声音文件  
        end;  
      end;  
      Wait(2000); // 等待2秒  
    end;  
  end;  
  
  // 如果启用了声音报警  
  if BaoJingSheng then  
  begin  
    // 检查是否有特定的Gump窗口打开  
    if GetGumpsCount > 0 then  
    begin  
      for h := 0 to (GetGumpsCount - 1) do  
      begin  
        if GetGumpID(h) = 3279111667 then // 如果Gump的ID等于3279111667  
        begin  
          if (timer - BaoJingShiChang) >= 8000 then // 如果距离上次报警超过8秒  
          begin  
            AddToSystemJournal('赶紧填写验证码！！！'); // 添加日志提示填写验证码  
            BaoJingShiChang := timer; // 更新上次报警时间  
            PlayWav(ShengYinWenJian); // 播放报警声音文件  
          end;  
          Break; // 跳出循环  
        end;  
      end;  
    end;  
  
    // 检查是否有GM巡查或特定物品在地面  
    for n := 0 to Length(GMName) - 1 do  
    begin  
      if (FindType($03DB, Ground) > 0) or (InJournal(GMName[n] + ': ') > -1) then  
      begin  
        if (timer - BaoJingShiChang) >= 8000 then // 如果距离上次报警超过8秒  
        begin  
          AddToSystemJournal('GM巡查了，快看一下！！！'); // 添加日志提示GM巡查  
          BaoJingShiChang := timer; // 更新上次报警时间  
          PlayWav(ShengYinWenJian); // 播放报警声音文件  
        end;  
      end;  
    end;  
  
    // 如果距离上次报警超过16秒，则重置报警时间  
    if (timer - BaoJingShiChang) >= 16000 then  
      BaoJingShiChang := timer - 8000;  
  end;  
end;
  
// 过程：报告统计信息  
procedure _BaoGao;  
begin  
  // 计算总运行时长  
  ZongShiChang := timer - QiDongShiJian;  
  
  // 计算天数  
  TianShu := Trunc(ZongShiChang / 86400000);  
  
  // 计算剩余时长（减去已计算的天数）  
  ShengYuShiChang := ZongShiChang - (TianShu * 86400000);  
  
  // 计算小时数  
  XiaoShiSHu := Trunc(ShengYuShiChang / 3600000);  
  
  // 更新剩余时长（减去已计算的小时数）  
  ShengYuShiChang := ShengYuShiChang - (XiaoShiSHu * 3600000);  
  
  // 计算分钟数  
  FenZhongShu := Trunc(ShengYuShiChang / 60000);  
  
  // 更新剩余时长（减去已计算的分钟数）  
  ShengYuShiChang := ShengYuShiChang - (FenZhongShu * 60000);  
  
  // 计算秒数  
  MiaoZhongShu := Trunc(ShengYuShiChang / 1000);  
  
  // 拼接运行时长字符串  
  YunXingShiChang := '脚本运行时长: ';  
  if TianShu > 0 then YunXingShiChang := YunXingShiChang + IntToStr(TianShu) + ' 天 ';  
  if XiaoShiSHu > 0 then YunXingShiChang := YunXingShiChang + IntToStr(XiaoShiSHu) + ' 小时 ';  
  if FenZhongShu > 0 then YunXingShiChang := YunXingShiChang + IntToStr(FenZhongShu) + ' 分 ';  
  if MiaoZhongShu > 0 then YunXingShiChang := YunXingShiChang + IntToStr(MiaoZhongShu) + ' 秒';  
  
  // 将运行时长添加到系统日志  
  AddToSystemJournal(YunXingShiChang + '；');  
  
  // 计算统计时长（小时为单位）  
  TongJiShiChang := ZongShiChang / 3600000;  
  
  // 检查背包中特定类型的物品数量  
  if FindTypesArrayEx([$1BD7], [0, 2010, 1191, 1192, 1193, 1194, 1151], [backpack], false) > 0 then  
    MuBanShu := MuBanZongJiShu + FindFullQuantity  
  else  
    MuBanShu := MuBanZongJiShu;  
  
  // 将砍到的木头数量和平均每小时砍到的木头数量添加到系统日志  
  AddToSystemJournal('共砍到木头 ' + IntToStr(MuBanShu) + '，平均每小时 ' +  
                     IntToStr(Round(MuBanShu / TongJiShiChang)) + '；');  
end;
  
// 函数：劈木板  
function _PiMuBan: Boolean;  
begin  
  Result := False; // 初始化返回结果为False  
  Setlength(SouSuoJieGuo, 0); // 清空搜索结果数组  
  FindType($1BDD, Backpack); // 在背包中查找类型为$1BDD的物品  
  CheckLag(400); // 检查延迟，等待400毫秒  
    
  // 获取找到的物品列表  
  SouSuoJieGuo := GetFoundItems;  
    
  if Length(SouSuoJieGuo) > 0 then // 如果找到了物品  
  begin  
    for i := 0 to Length(SouSuoJieGuo) - 1 do // 遍历找到的物品列表  
    begin  
      CancelTarget; // 取消当前目标  
      UseObject(ObjAtLayer(LhandLayer)); // 使用左手层的物品（可能是工具）  
      WaitForTarget(1000); // 等待目标出现，假设是等待劈木板动作的准备时间  
      TargetToObject(SouSuoJieGuo[i]); // 将目标设置为当前物品  
      AddToSystemJournal('劈木板中。。。'); // 在系统日志中添加消息  
      Wait(600); // 等待劈木板动作的完成时间  
    end;  
      
    Result := True; // 设置返回结果为True，表示劈木板完成  
    AddToSystemJournal('完成，当前负重 ' + IntToStr(Weight) + '/' + IntToStr(ZuiDaFuZhong)); // 在系统日志中添加当前负重信息  
  end;  
end;  
  
// 函数：获取当前负重  
function _FuZhong: Word;  
begin  
  Result := 0; // 初始化返回结果为0  
  DangQianFuZhong := 0; // 初始化当前负重为0  
    
  repeat  
    _DuanXianJianCe; // 调用断线重连检测过程  
    DangQianFuZhong := Weight; // 获取当前负重  
  until DangQianFuZhong <> 0; // 循环直到获取到非零的当前负重  
    
  Result := DangQianFuZhong; // 返回当前负重  
end;
  
// 过程：飞行到指定地点  
procedure _FeiXing(FeiShu: Cardinal; FeiDian: Byte; HuanDian: Boolean);  
begin  
  // 设置飞行目的地为参数FeiDian  
  FuShi := FeiDian;  
  // 获取当前坐标  
  nowX := _Du_X_ZuoBiao;  
  nowY := _Du_Y_ZuoBiao;  
  // 清除系统日志  
  ClearJournal;  
  
  // 当坐标未改变时，持续循环  
  while (nowX = _Du_X_ZuoBiao) and (nowY = _Du_Y_ZuoBiao) do  
  begin  
    // 关闭所有可以关闭的Gump界面  
    while IsGump and IsGumpCanBeClosed(GetGumpsCount - 1) do  
    begin  
      CloseSimpleGump(GetGumpsCount - 1);  
      _yiwai; // 处理意外情况  
    end;  
  
    // 使用飞行卷轴  
    UseObject(FeiShu);  
    waiMS2 := 0; // 初始化等待计数器  
  
    // 等待飞行界面出现  
    while GetGumpID(GetGumpsCount - 1) <> 1431013363 do  
    begin  
      Wait(100); // 等待100毫秒  
      waiMS2 := waiMS2 + 1; // 增加等待计数器  
  
      // 如果等待超过一定时间，则重试飞行和检查存盘  
      if waiMS2 >= 40 then  
      begin  
        _yiwai; // 处理意外情况  
        _CunPanJianCe; // 检查存盘情况  
        UseObject(FeiShu); // 再次使用飞行卷轴  
        waiMS2 := 0; // 重置等待计数器  
      end;  
    end;  
  
    // 如果当前负重超过最大负重，则劈木板减轻负重  
    while (_FuZhong > ZuiDaFuZhong) do  
      _PiMuBan;  
  
    waiMS2 := 0; // 重置等待计数器  
  
    // 如果飞行界面已出现  
    if GetGumpID(GetGumpsCount - 1) = 1431013363 then  
    begin  
      // 选择飞行技能按钮  
      NumGumpButton(GetGumpsCount - 1, (FeiXingJiNeng + (FuShi - 1) * 6));  
  
      // 根据是否需要返回原点更新目的地  
      if HuanDian then  
      begin  
        if (FuShi = FeiDian) then  
          FuShi := FuShi + 1  
        else  
          FuShi := FeiDian;  
      end;  
  
      // 等待坐标改变或遇到阻塞或超时  
      repeat  
        Wait(500); // 等待500毫秒  
        waiMS2 := waiMS2 + 1; // 增加等待计数器  
      until (nowX <> _Du_X_ZuoBiao) or (nowY <> _Du_Y_ZuoBiao) or (InJournal('blocked') > -1) or (waiMS2 >= 8);  
  
      // 如果遇到阻塞，则清除日志并根据是否需要返回原点决定是否中断  
      if (InJournal('blocked') > -1) then  
      begin  
        ClearJournal;  
        if not HuanDian then  
          Break; // 如果不需要返回原点，则中断循环  
      end;  
    end;  
  
    _yiwai; // 处理意外情况  
  end;  
end;
  
// 过程：放置木板和副产品  
procedure _FangChengGuo;  
begin  
  // 如果背包中存在特定类型的木板  
  if FindTypesArrayEx([$1BD7], [0, 2010, 1191, 1192, 1193, 1194, 1151], [backpack], false) > 0 then  
  begin  
    AddToSystemJournal('放木板中。。。');  
    // 将找到的木板数量加到总数量上  
    MuBanZongJiShu := MuBanZongJiShu + FindFullQuantity;  
    // 将木板移动到木头箱  
    MoveItems(backpack, $1BD7, -1, MuTouXiang, 0, 0, 0, 600);  
    CheckLag(6000); // 检查延迟  
  end;  
  
  // 遍历副产品类型数组  
  for i := 0 to Length(FuChanPinTuXing) - 1 do  
  begin  
    // 如果背包中存在当前副产品  
    if FindType(FuChanPinTuXing[i], backpack) > 0 then  
    begin  
      AddToSystemJournal('放副产品中。。。');  
      // 将副产品移动到木头箱  
      MoveItems(backpack, FuChanPinTuXing[i], -1, MuTouXiang, 0, 0, 0, 600);  
      CheckLag(1200); // 检查延迟  
    end;  
  end;  
end; 
  

// 主程序入口（可能还需要其他初始化代码）  
begin  
  // ... (前面的代码被省略了，但假设它是某个主过程或函数的开始)  
  
  _DuQuZuoBiaoWenJian; // 调用读取坐标文件的函数（具体实现未给出）  
  JianCeZuoBiao := False; // 初始化坐标检查标志为False  
  
  // 初始化树图类型数组  
  Setlength(ShuTuXing, 45);  
  ShuTuXing[0] := 3240; // ... (其他元素被初始化，省略以节省空间)  
  // ...  
  ShuTuXing[44] := 3488;  
  
  // 初始化副产品类型数组  
  Setlength(FuChanPinTuXing, 5);  
  FuChanPinTuXing[0] := $318F; // ... (其他元素被初始化，省略以节省空间)  
  // ...  
  FuChanPinTuXing[4] := $2F5F;  
  
  // 初始化飞书ID数组  
  Setlength(FaMuShu, 5);  
  FaMuShu[0] := DiYiBenFaMuShu; // ... (其他元素被初始化，省略以节省空间)  
  // ...  
  FaMuShu[4] := DiWuBenFaMuShu;  
  
  _GMLieBiao; // 调用GM列表函数（具体实现未给出）  
  
  // 根据伐木方向设置偏移量  
  case FaMuFangXiang of  
    0: begin XPianYi := 0; YPianYi := -1; end; // N  
    1: begin XPianYi := 1; YPianYi := 0; end;  // E  
    2: begin XPianYi := 0; YPianYi := 1; end;  // S  
    3: begin XPianYi := -1; YPianYi := 0; end; // W  
  end;  
  
  MuBanZongJiShu := 0; // 重置木板总数为0  
  
  // 检查是否连接，如果未连接则尝试连接  
  if not Connected then  
  begin  
    Connect;  
    waiMS := 0;  
    repeat  
      Wait(500);  
      waiMS := waiMS + 1;  
      AddToSystemJournal('ID不在线，登录中...');  
      if waiMS >= 10 then  
      begin  
        if InJournal('reason : Another character from this account') > -1 then  
        begin  
          AddToSystemJournal('当前账号下的其他ID在线，无法登录，脚本终止');  
          Halt; // 终止程序  
        end;  
        Connect;  
        waiMS := 0;  
      end;  
    until Connected;  
  end;  
  
  BaoJingShiChang := timer - 8000; // 更新报警时间  
  QiDongShiJian := timer; // 记录启动时间  
  AddToSystemJournal('欢迎使用alone脱机伐木脚本，版本2022.08.17');  
  
  // 等待最大负重更新  
  repeat  
    ZuiDaFuZhong := MaxWeight;  
    Wait(50);  
  until ZuiDaFuZhong > 0;  
  
  // 如果当前位置距离木头箱较远，则先飞到木头箱前  
  if (Dist(_Du_X_ZuoBiao, _Du_Y_ZuoBiao, MuTouXiang_X, MuTouXiang_Y) > 2) then  
  begin  
    AddToSystemJournal('先飞到木头箱前');  
    _FeiXing(FeiHuiShu, DiYiHuiJiaDian, True); // 使用回家飞书飞到指定位置  
  end;  
  
  // 根据当前负重设置劈木板阈值  
  if ZuiDaFuZhong > 550 then  
    PiYuZhi := 484  
  else  
    PiYuZhi := ZuiDaFuZhong - 66;  
  HuiYuZhi := PiYuZhi + 22; // 设置回程阈值  
  
  // 如果启用了喊Guard功能，则设置相关事件和计数器  
  if ZhaoWeiBing then  
  begin  
    WeiBingShiJian := 0;  
    SetEventProc(evTimer1, '_HanWeiBing'); // 设置定时器事件处理函数  
  end;  
  SetEventProc(evTimer2, '_FangZhaDan'); // 设置另一个定时器事件处理函数  
  SetEventProc(evIncomingGump, '_DuiHuaKuangJianCe'); // 设置Gump窗口事件处理函数  
  JianCeZuoBiao := True; // 设置坐标检查标志为True  
  
  // 遍历伐木点和飞书  
  for j := 1 to 5 do // 假设有5本书  
  begin  
    for k := 1 to 16 do // 每本书有16个点  
    begin  
      // 如果当前位置接近木头箱，则放木板和报告统计信息  
      if (Dist(_Du_X_ZuoBiao, _Du_Y_ZuoBiao, MuTouXiang_X, MuTouXiang_Y) < 3) then  
      begin  
        _FangChengGuo; // 放木板  
        _BaoGao; // 报告统计信息  
      end;  
  
      AddToSystemJournal('飞往下一个伐木点。。。');  
      _FeiXing(FaMuShu[j - 1], k, False); // 使用当前飞书飞到下一个点  
      ClearJournal; // 清除系统日志  
      TaoGuo := True; // 设置逃跑标志为True（具体作用未明确给出）  
  
      // 如果当前位置距离木头箱较远，则输出日志并开始砍树逻辑  
      if (Dist(_Du_X_ZuoBiao, _Du_Y_ZuoBiao, MuTouXiang_X, MuTouXiang_Y) > 2) then  
      begin  
        AddToSystemJournal('正在第 ' + IntToStr(j) + ' 本书的第 ' + IntToStr(k) + ' 个点努力砍树');  
        // ... (砍树逻辑被省略，但假设它包含检查树图、使用斧头、逃跑炸弹等步骤)  
      end;  
    end;  
    if (j = 5) then j := 0; // 循环回到第一本书（假设需要循环）  
  end;  
end;
  
